package com.wzdigit.wms.wms.service.mid;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.wzdigit.framework.Shift;
import com.wzdigit.mes.basic.api.BasicDataItemDetailApi;
import com.wzdigit.mes.basic.api.BasicGetCustomerApi;
import com.wzdigit.mes.basic.api.BasicSimpleCodeRuleApi;
import com.wzdigit.mes.basic.dto.CustomerDto;
import com.wzdigit.mes.basic.dto.DataItemDetailDTO;
import com.wzdigit.wms.basic.domain.basic.Sku;
import com.wzdigit.wms.basic.domain.inventory.Lotno;
import com.wzdigit.wms.basic.domain.mid.IfShipnoticeDtl;
import com.wzdigit.wms.basic.domain.mid.IfShipnoticeHeader;
import com.wzdigit.wms.basic.domain.mid.JobSyncErrorData;
import com.wzdigit.wms.basic.domain.mid.dtos.IfShipnoticeHeaderDto;
import com.wzdigit.wms.basic.domain.transfer.CtnrLoading;
import com.wzdigit.wms.basic.domain.transfer.GdnDtl;
import com.wzdigit.wms.basic.domain.transfer.GdnHeader;
import com.wzdigit.wms.basic.enums.GdnDtlStatusEnum;
import com.wzdigit.wms.basic.enums.GdnHeaderStatusEnum;
import com.wzdigit.wms.basic.enums.GdnTypeEnum;
import com.wzdigit.wms.basic.mapper.core.basic.SkuMapper;
import com.wzdigit.wms.basic.mapper.core.mid.IfShipnoticeDtlMapper;
import com.wzdigit.wms.basic.mapper.core.mid.IfShipnoticeHeaderMapper;
import com.wzdigit.wms.basic.mapper.core.mid.JobSyncErrorDataMapper;
import com.wzdigit.wms.basic.mapper.core.transfer.CtnrLoadingMapper;
import com.wzdigit.wms.basic.mapper.core.transfer.GdnDtlMapper;
import com.wzdigit.wms.basic.mapper.core.transfer.GdnHeaderMapper;
import com.wzdigit.wms.wms.constant.SyncTypeConstant;
import com.wzdigit.wms.wms.exception.SyncException;
import com.wzdigit.wms.basic.service.code.LotnoService;
import lombok.extern.slf4j.Slf4j;
import net.dreamlu.mica.core.utils.BeanUtil;
import net.dreamlu.mica.core.utils.CollectionUtil;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 接口中间表-发货通知单表头 服务类
 * </p>
 *
 * @author
 * @since 2021-03-12
 */
@Service
@Slf4j
public class IfShipnoticeHeaderService {

    @Autowired
    private IfShipnoticeHeaderMapper ifShipnoticeHeaderMapper;

    @Autowired
    private IfShipnoticeDtlMapper ifShipnoticeDtlMapper;

    @Autowired
    private GdnHeaderMapper gdnHeaderMapper;

    @Autowired
    private GdnDtlMapper gdnDtlMapper;

    @Autowired
    private SkuMapper skuMapper;

    @Autowired
    private LotnoService lotnoService;

    @Autowired
    private SyncErrorDataService syncErrorDataService;

    @Autowired
    private JobSyncErrorDataMapper jobSyncErrorDataMapper;

    @Autowired
    private CtnrLoadingMapper ctnrLoadingMapper;

    @Reference(version = "${dubbo.providers.basic.customer.api.version:1.0.0}", check = false, timeout = 300000)
    private BasicGetCustomerApi basicGetCustomerApi;

    @Reference(version = "${dubbo.consumers.basic.data.item.detail.api:1.0.0}", check = false, timeout = 300000)
    private BasicDataItemDetailApi dataItemDetailApi;

    @Reference(version = "${dubbo.consumers.basic.simple.code.rule.api:1.0.0}", check = false)
    BasicSimpleCodeRuleApi basicSimpleCodeRuleApi;

    @Value(value = "${default_owner.code}")
    private String DEFAULT_OWNER;

    @Value(value = "${default_owner.name}")
    private String DEFAULT_OWNER_NAME;

    @Value("${order_code.gdn.code}")
    private String gdnNoRule;

    private final String syncType = SyncTypeConstant.IF_SHIPNOTICE_TO_GDN;

    public List<IfShipnoticeHeaderDto> selectSyncData() {
        ArrayList<IfShipnoticeHeaderDto> ifShipnoticeHeaderDtos = new ArrayList<>();
        List<IfShipnoticeHeader> selectSyncData = ifShipnoticeHeaderMapper.selectByFlag();
        if (!CollectionUtil.isEmpty(selectSyncData)) {
            for (IfShipnoticeHeader ifShipnoticeHeader : selectSyncData) {
                IfShipnoticeHeaderDto ifShipnoticeHeaderDto = new IfShipnoticeHeaderDto();
                List<IfShipnoticeDtl> ifShipnoticeDtls = ifShipnoticeDtlMapper.selectList(new QueryWrapper<>(
                        new IfShipnoticeDtl().setIfShipnoticeHeaderId(ifShipnoticeHeader.getIfShipnoticeHeaderId())));
                BeanUtil.copyNonNull(ifShipnoticeHeader, ifShipnoticeHeaderDto);
                ifShipnoticeHeaderDto.setIfShipnoticeDtlList(ifShipnoticeDtls);
                ifShipnoticeHeaderDtos.add(ifShipnoticeHeaderDto);
            }
        }
        return ifShipnoticeHeaderDtos;
    }

    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    public void syncData(IfShipnoticeHeaderDto data, boolean isSyncError) throws Exception {
        String noticeNo = data.getNoticeNo();
        Integer lockMaxGdnLineNo = 0;
        List<IfShipnoticeDtl> ifShipnoticeDtlList = data.getIfShipnoticeDtlList();
        if (CollectionUtil.isEmpty(ifShipnoticeDtlList)) {
            throw new SyncException(syncType, noticeNo, "发货单下没有明细");
        }
        Map<String, List<IfShipnoticeDtl>> group = ifShipnoticeDtlList.stream().collect(
                Collectors.groupingBy(IfShipnoticeDtl::getRefCtnrNo));
        Set<String> refCtnrNoList = group.keySet();
        for (Iterator i = refCtnrNoList.iterator(); i.hasNext(); ) {

            //相同参考柜号组成GDN主档
            List<IfShipnoticeDtl> ifShipnoticeDtls = group.get(i.next());
            IfShipnoticeDtl ifShipnoticeDtl = ifShipnoticeDtls.get(0);
            GdnHeader gdnHeader = new GdnHeader();
            //发货单号系统生成
            //生成发货单号
            String gdnNo = null;
            try {
                gdnNo = this.basicSimpleCodeRuleApi.GenerateCode(this.gdnNoRule);
            } catch (Exception e) {
                throw new SyncException(syncType, noticeNo, "生成发货单号失败" + (e == null ? e : e.getMessage()));
            }
            gdnHeader.setGdnNo(gdnNo);
            gdnHeader.setSourceShipNotice(noticeNo);
            gdnHeader.setFactory(data.getOrgCode());
            CustomerDto customer = basicGetCustomerApi.getCustomerByCode(data.getCustomerCode());
//            if (customer == null) {
//                throw new SyncException(syncType, noticeNo, "客户" + data.getCustomerCode() + "不存在");
//            }
            if (customer != null) {
                gdnHeader.setCustomer(customer.getCustomerId());
            }
            gdnHeader.setClosingDate(data.getCloseTime());
            gdnHeader.setShipDate(data.getShipTime());
            if ("内销".equals(data.getSaleType())) {
//                gdnHeader.setSaleType(0);原来的
                gdnHeader.setSaleType(1);
            }
            if ("外销".equals(data.getSaleType())) {
//                gdnHeader.setSaleType(1);原来的
                gdnHeader.setSaleType(2);
            } else {
                gdnHeader.setSaleType(-1);
            }
            gdnHeader.setGdnType(GdnTypeEnum.D01.code);
            gdnHeader.setExportCountry(data.getExportCountry());
            gdnHeader.setShipPort(data.getShipPort());
            gdnHeader.setStatus(GdnHeaderStatusEnum.CREATE.code);
            gdnHeader.setGdnCreateTime(data.getCreateTime());
            gdnHeader.setGdnCreateUser(data.getCreateUser());
            gdnHeader.setComments(data.getRemarks());
            DataItemDetailDTO dataItem = dataItemDetailApi.getDataItemDetailByPCodeAndName(DEFAULT_OWNER, DEFAULT_OWNER_NAME);
            gdnHeader.setOwner(dataItem == null || dataItem.getItemValue() == null ? 0 : Integer.parseInt(dataItem.getItemValue()));
            gdnHeader.setRefCntrNo(ifShipnoticeDtl.getRefCtnrNo());
            gdnHeader.setCntrType(ifShipnoticeDtl.getRefCtnrType());
            gdnHeader.setCntrSeq(ifShipnoticeDtl.getCtnrSeq());
            gdnHeader.setExportCountry(data.getExportCountry());
            gdnHeader.setPlanLoadingTime(ifShipnoticeDtl.getPlanLoadingTime());

            gdnHeader.setComments(ifShipnoticeDtl.getRemarks());//备注，header的备注取dtl的任意一个

            gdnHeader.setCntrNo(ifShipnoticeDtl.getCtnrNo());//实际柜号
            gdnHeader.setBookingNo(ifShipnoticeDtl.getBookingNo());//订舱号
            gdnHeader.setSealNo(ifShipnoticeDtl.getSealNo());//封条号
            gdnHeader.setVehicleNo(ifShipnoticeDtl.getVehicleNo());//车牌号


            GdnHeader headerRecord = gdnHeaderMapper.selectOne(new QueryWrapper<>(new GdnHeader().setSourceShipNotice(noticeNo).setRefCntrNo(gdnHeader.getRefCntrNo())));
            //TODO ZYF:如果发货单关单了是不允许修改的
            if (headerRecord!=null){
                if (headerRecord.getStatus().equals(GdnHeaderStatusEnum.FINISH.code)||headerRecord.getStatus().equals(GdnHeaderStatusEnum.CLOSE.code)){
                    log.info("源单号SourceShipNotice["+noticeNo+"]已关单，无法同步!");
                    continue;
                }
            }

            if (headerRecord == null) {
                gdnHeader.setCreateTime(new Date());
                gdnHeader.setCreateUser("system");
                gdnHeaderMapper.insert(gdnHeader);
            } else {
                gdnHeader.setStatus(null);  //变更单据，不变更主档状态
                Integer status = headerRecord.getStatus();
                //4:完成，5:关闭
                int finishCode = GdnHeaderStatusEnum.FINISH.getCode();
                int closeCode = GdnHeaderStatusEnum.CLOSE.getCode();

                if (status != finishCode || status != closeCode) {
                    // 锁住最大行号
                    lockMaxGdnLineNo = gdnDtlMapper.lockMaxGdnLineNo(headerRecord.getGdnHeaderId());

                    gdnHeader.setGdnNo(headerRecord.getGdnNo());
                    gdnHeader.setGdnHeaderId(headerRecord.getGdnHeaderId());
                    gdnHeader.setModifyTime(new Date());
                    gdnHeader.setModifyUser("system");
                    gdnHeaderMapper.updateById(gdnHeader);

                    //更新装柜单信息:实际柜号,订舱号,封条号,车牌号
                    //创建类型的条件构造器
                    QueryWrapper<CtnrLoading> wrapper = new QueryWrapper<>();
                    wrapper.eq("GDN_NO", gdnHeader.getGdnNo());

                    //根据发货单单头的单号查询装柜单
                    List<CtnrLoading> ctnrLoadingList = ctnrLoadingMapper.selectList(wrapper);
                    if (ctnrLoadingList.size()>0) {

                        CtnrLoading ctnrLoading = new CtnrLoading();
                        ctnrLoading.setCntrNo(gdnHeader.getCntrNo());
                        ctnrLoading.setBookingNo(gdnHeader.getBookingNo());
                        ctnrLoading.setSealNo(gdnHeader.getSealNo());
                        ctnrLoading.setVehicleNo(gdnHeader.getVehicleNo());
                        ctnrLoading.setModifyTime(new Date());
                        ctnrLoading.setModifyUser("system");

                        //创建类型的条件构造器
                        QueryWrapper<CtnrLoading> wrapperUpdate = new QueryWrapper<>();
                        wrapperUpdate.eq("GDN_NO", gdnHeader.getGdnNo());
                        ctnrLoadingMapper.update(ctnrLoading, wrapperUpdate);
                    }

                }
            }

            for (IfShipnoticeDtl shipnoticeDtl : ifShipnoticeDtls) {
                //明细插入明细
                GdnDtl gdnDtl = new GdnDtl();
                BeanUtil.copyNonNull(shipnoticeDtl, gdnDtl);
                gdnDtl.setGdnHeaderId(gdnHeader.getGdnHeaderId());
                if (shipnoticeDtl.getOldSoNo() == null) {
                    gdnDtl.setSoNo(shipnoticeDtl.getSoNo());
                } else {
                    gdnDtl.setRefSoNo(shipnoticeDtl.getSoNo());
                    gdnDtl.setSoNo(shipnoticeDtl.getOldSoNo());
                }
                if (shipnoticeDtl.getOldSoLineNo() == null) {
                    gdnDtl.setSoLineNo(shipnoticeDtl.getSoLineNo());
                } else {
                    gdnDtl.setSoLineNo(shipnoticeDtl.getOldSoLineNo());
                    gdnDtl.setRefSoLineNo(shipnoticeDtl.getSoLineNo());
                }
                gdnDtl.setShipQty(BigDecimal.ZERO);
                gdnDtl.setModleType(shipnoticeDtl.getModelType());
                gdnDtl.setCustomerModle(shipnoticeDtl.getCustomerModel());
                gdnDtl.setBrand(shipnoticeDtl.getBrand());
                Sku sku = skuMapper.selectOne(new QueryWrapper<>(new Sku().setSkuCode(shipnoticeDtl.getMaterialCode())));
                if (sku == null) {
                    throw new SyncException(syncType, noticeNo, "物料" + shipnoticeDtl.getMaterialCode() + "不存在");
                }
                gdnDtl.setSourceShipNoticeItem(shipnoticeDtl.getInvoiceLineNo());
                gdnDtl.setGdnLineNo(++lockMaxGdnLineNo);
                gdnDtl.setSkuId(sku.getSkuId());
                gdnDtl.setUnit(sku.getBaseUnit());
                gdnDtl.setOrderQty(shipnoticeDtl.getShipQty());
                gdnDtl.setComments(shipnoticeDtl.getRemarks());
                if(shipnoticeDtl.getAttribute4() == null){
                    gdnDtl.setPoNo(shipnoticeDtl.getAttribute1());
                    gdnDtl.setUdf4(shipnoticeDtl.getAttribute4());
                }else{
                    gdnDtl.setPoNo(shipnoticeDtl.getAttribute4());
                    gdnDtl.setUdf4(shipnoticeDtl.getAttribute1());
                }
                gdnDtl.setQaStatus(1);
                gdnDtl.setStatus(GdnDtlStatusEnum.CREATE.code);

                gdnDtl.setGdnRef1(shipnoticeDtl.getAttribute3());//同步OMS发货通知单接口的明细表，增加“需要加装配管”这个字段，放在ATTRIBUTE3，存在WMS_GDN_DTL的GDN_REF1字段

                List<Long> gdnDtlIdList = null;
                List<GdnDtl> dtlRecord = gdnDtlMapper.selectList(new QueryWrapper<>(new GdnDtl().setSourceShipNoticeItem(shipnoticeDtl.getInvoiceLineNo()).setGdnHeaderId(gdnHeader.getGdnHeaderId())));
                if (dtlRecord == null || dtlRecord.size()==0) {
                    gdnDtl.setCreateTime(new Date());
                    gdnDtl.setCreateUser("system");
                    try {
                        gdnDtlMapper.insert(gdnDtl);
                        gdnDtlIdList = new ArrayList(1);
                        gdnDtlIdList.add(gdnDtl.getGdnDtlId());
                    } catch (Exception e) {
                        e.printStackTrace();
                        throw new SyncException(syncType, noticeNo, "发货单明细行新增失败：" + e.getMessage());
                    }
                } else {
//                    gdnDtl.setGdnDtlId(dtlRecord.getGdnDtlId());
                    gdnDtl.setShipQty(null);
                    gdnDtl.setOrderQty(null);
                    gdnDtl.setStatus(null);
                    gdnDtl.setGdnLineNo(null);
                    gdnDtl.setModifyTime(new Date());
                    gdnDtl.setModifyUser("system");
                    try {
                        gdnDtlIdList = dtlRecord.stream().map(d -> d.getGdnDtlId()).collect(Collectors.toList());
                        QueryWrapper queryWrapper = new QueryWrapper<GdnDtl>();
                        queryWrapper.in("GDN_DTL_ID", gdnDtlIdList);
                        gdnDtlMapper.update(gdnDtl, queryWrapper);
//                        gdnDtlMapper.updateById(gdnDtl);
                    } catch (Exception e) {
                        throw new SyncException(syncType, noticeNo, "发货单明细行修改失败：" + e.getMessage());
                    }
                }

                for(Long gdeDtlId : gdnDtlIdList){
                    //生成批次号
                    Lotno lotno = lotnoService.getLotnoByGdnDtlId(gdeDtlId);

                    if (lotno != null) {
                        log.info("发货单明细：批次号{},ID{}", lotno.getLotno(), gdeDtlId);
                        gdnDtl.setGdnDtlId(gdeDtlId);
                        gdnDtl.setLotno(lotno.getLotno());
                        int r = 1;
                        try {
                            r = setLotAttr(gdnDtl, lotno);
                        } catch (Exception e) {
                            e.printStackTrace();
                            throw new SyncException(syncType, noticeNo, "设置批次属性" + r + "失败");
                        }
                        gdnDtlMapper.updateLotNoAndAttr(gdnDtl);
                    }
                }
            }
            //更新状态为已同步
            int row = ifShipnoticeHeaderMapper.updateFlagById(data.getIfShipnoticeHeaderId());
            //检查是否有同步失败的记录，有则更新为成功
            JobSyncErrorData jobSyncErrorData = jobSyncErrorDataMapper.getSyncErrorDataByTypeAndCode(syncType, noticeNo);
            if (jobSyncErrorData != null && 0 == jobSyncErrorData.getIsSuccess()) {
                syncErrorDataService.updateSuccessByCode(syncType, noticeNo);
            }
            log.info("---------发货通知单success-------");
        }
    }

    /**
     * 设置批次属性1~12
     *
     * @param obj
     * @param lotno
     */
    private int setLotAttr(Object obj, Lotno lotno) throws Exception {
        int i = 1;
        for (i = 1; i < 13; i++) {
            try {
                Class<?> aClass = obj.getClass();
                Object value = lotno.getClass().getMethod("getLotAttr" + i).invoke(lotno, null);
                Method method = aClass.getMethod("setLotAttr" + i, String.class);
                method.invoke(obj, value);
            } catch (Exception e) {
                e.printStackTrace();
                break;
            }
        }
        return i;
    }
}
